package com.shopx.base.aspect;

import com.shopx.base.anno.RepearSubmitChkAnno;
import com.shopx.base.constants.ResultCodeEnum;
import com.shopx.base.exception.OriginException;
import com.shopx.base.exception.ShopxException;
import com.shopx.core.utils.RSAUtils;
import com.shopx.core.utils.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.concurrent.TimeUnit;

@Aspect
@Component
@Slf4j
public class RepearSubmitChkAspect {
    @Autowired
    private StringRedisTemplate redisTemplate;

    @Value("${key.rsaPrivateKey:}")
    private String rsaPrivateKey;

    @SuppressWarnings("static-access")
    @Before("@annotation(anno)")
    public void before(JoinPoint join, RepearSubmitChkAnno anno) {
        int lockSeconds = anno.lockTime();
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        String path = request.getServletPath();

        String hmac = request.getHeader("hmac");
        if (StringUtil.isEmpty(hmac)) {
            //表单提交方式传递hamc
            hmac = request.getParameter("hmac");
        }
        if(hmac==null){
            return;
        }
        String tokenId = getTokenId(hmac);
        String key = tokenId + "_" + path;
        log.info("RepearSubmitChkAspect.key:{}",key);
        // 如果缓存中有这个url视为重复提交
        if (!redisTemplate.hasKey(key)) {
            log.info("没有key");
            redisTemplate.opsForValue().set(key, String.valueOf(0), lockSeconds, TimeUnit.SECONDS);
        } else {
            log.info("有key，重复提交");
            throw new ShopxException(ResultCodeEnum.OPR_FREQUENT_ERROR);
        }
    }

    /**
     * 解密获取令牌信息 格式（用户编号:令牌）
     * @author lituo
     * @date 1:45 PM 2021/12/6
     * @param	hmac
     * @return com.shopx.auth.dto.LoginUserDTO
     */
    private String getTokenId(String hmac) throws ShopxException {
        // 开始解密
        String decStr = "";
        try {
            decStr = RSAUtils.privateDecrypt(hmac, RSAUtils.getPrivateKey(rsaPrivateKey));
        } catch (Exception e) {
            throw new ShopxException(ResultCodeEnum.BUSI_SIGN_ERROR);
        }
        String tokenId = decStr.split(":")[1];
        return tokenId;
    }
}
